/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package me.zhengjie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.RequiredArgsConstructor;
import me.zhengjie.domain.KwExamRoom;
import me.zhengjie.exception.ParameterException;
import me.zhengjie.mapper.*;
import me.zhengjie.pojo.entity.*;
import me.zhengjie.repository.KwExamRoomRepository;
import me.zhengjie.repository.KwOccupyRepository;
import me.zhengjie.service.KwExamRoomService;
import me.zhengjie.service.dto.KwExamRoomDto;
import me.zhengjie.service.dto.KwExamRoomQueryCriteria;
import me.zhengjie.service.mapstruct.KwExamRoomMapper;
import me.zhengjie.util.KwUtils;
import me.zhengjie.utils.*;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LongYang
 * @website https://el-admin.vip
 * @description 服务实现
 * @date 2021-06-28
 **/
@Service
@RequiredArgsConstructor
public class KwExamRoomServiceImpl implements KwExamRoomService {

    private final KwExamRoomRepository kwExamRoomRepository;
    private final KwExamRoomMapper kwExamRoomMapper;
    private final KwOccupyRepository kwOccupyRepository;

    private final RoomMapper roomMapper;
    private final ExamRoomMapper examRoomMapper;
    private final ExamTeacherMapper examTeacherMapper;
    private final ExamStudentMapper examStudentMapper;
    private final OccupyMapper occupyMapper;
    private final KwUtils kwUtils;

    @Override
    public Map<String, Object> queryAll(KwExamRoomQueryCriteria criteria, Pageable pageable) {
        if (criteria.getExamId() == null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("content", new Object[0]);
            map.put("totalElements", 0);
            return map;
        }
        User user = kwUtils.getUser();

        Page<KwExamRoom> page = kwExamRoomRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(kwExamRoomMapper::toDto));
    }

    @Override
    public List<KwExamRoomDto> queryAll(KwExamRoomQueryCriteria criteria) {
        return kwExamRoomMapper.toDto(kwExamRoomRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public KwExamRoomDto findById(Integer id) {
        KwExamRoom kwExamRoom = kwExamRoomRepository.findById(id).orElseGet(KwExamRoom::new);
        ValidationUtil.isNull(kwExamRoom.getId(), "KwExamRoom", "id", id);
        return kwExamRoomMapper.toDto(kwExamRoom);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public KwExamRoomDto create(KwExamRoom resources) {
        Room room = roomMapper.selectById(resources.getRoomId());
        if (room != null && resources.getSeatNumber() > room.getSeatNumber())
            throw new ParameterException("该教室只能容纳" + room.getSeatNumber() + "人");
        if (StringUtils.isNotBlank(resources.getNameCn())) {
            QueryWrapper<ExamRoom> wrapper = new QueryWrapper<>();
            wrapper.eq("name_cn", resources.getNameCn());
            Integer count = examRoomMapper.selectCount(wrapper);
            if (count != 0) throw new ParameterException("考场名已存在,不可重复");
        }

        return kwExamRoomMapper.toDto(kwExamRoomRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(KwExamRoom resources) {
        Room room = roomMapper.selectById(resources.getRoomId());
        if (room != null && resources.getSeatNumber() > room.getSeatNumber())
            throw new ParameterException("该教室只能容纳" + room.getSeatNumber() + "人");

        if (StringUtils.isNotEmpty(resources.getNameCn())) {
            QueryWrapper<ExamRoom> wrapper = new QueryWrapper<>();
            wrapper.eq("name_cn", resources.getNameCn())
                    .ne("id", resources.getId());
            Integer count = examRoomMapper.selectCount(wrapper);
            if (count != 0) throw new ParameterException("考场名已存在,不可重复");
        }

        KwExamRoom kwExamRoom = kwExamRoomRepository.findById(resources.getId()).orElseGet(KwExamRoom::new);
        ValidationUtil.isNull(kwExamRoom.getId(), "KwExamRoom", "id", resources.getId());
        kwExamRoom.copy(resources);
        kwExamRoomRepository.save(kwExamRoom);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(Integer[] ids) {
        List<KwExamRoom> kwExamRooms = kwExamRoomRepository.findAllById(Arrays.asList(ids));
        List<Integer> examIds = kwExamRooms.stream().map(KwExamRoom::getExamId).collect(Collectors.toList());
        boolean permission = kwUtils.hasOtherPermission(examIds);
        if (!permission) {
            throw new ParameterException("无权操作");
        }

        for (Integer id : ids) {
            KwExamRoom kwExamRoom = kwExamRoomRepository.findFirstById(id);
            /*删除考生安排表、教师安排表的考场信息、该教师的这场考试占用信息*/
            QueryWrapper<ExamTeacher> examTeacherQueryWrapper = new QueryWrapper<>();
            examTeacherQueryWrapper.eq("exam_room_id", id);
            List<ExamTeacher> examTeachers = examTeacherMapper.selectList(examTeacherQueryWrapper);
            if (!examTeachers.isEmpty()) {
                for (ExamTeacher examTeacher : examTeachers) {
                    QueryWrapper<Occupy> occupyQueryWrapper = new QueryWrapper<>();
                    occupyQueryWrapper.eq("exam_id", examTeacher.getExamId())
                            .eq("type_id", examTeacher.getTeacherId())
                            .eq("type", "1");
                    occupyMapper.delete(occupyQueryWrapper);
                }
            }
            UpdateWrapper<ExamTeacher> wrapper = new UpdateWrapper<>();
            wrapper.eq("exam_room_id", id)
                    .set("exam_room_id", null)
                    .set("room_id", null);
            examTeacherMapper.update(null, wrapper);


            UpdateWrapper<ExamStudent> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("exam_room_id", id)
                    .set("exam_room_id", null)
                    .set("room_id", null);
            examStudentMapper.update(null, updateWrapper);

            Integer examId = kwExamRoom.getExamId();
            Integer typeId = kwExamRoom.getRoomId();
            kwOccupyRepository.deleteByExamIdAndTypeId(examId, typeId);
            kwExamRoomRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<KwExamRoomDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (KwExamRoomDto kwExamRoom : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("考试id", kwExamRoom.getExamId());
            map.put("教室id", kwExamRoom.getRoomId());
            map.put("考场名称", kwExamRoom.getNameCn());
            map.put("教室名称", kwExamRoom.getRoomName());
            map.put("地点", kwExamRoom.getAddress());
            map.put("座位数量", kwExamRoom.getSeatNumber());
            map.put("删除标识（0：未删除，1：已删除）", kwExamRoom.getDelFlag());
            map.put("备注", kwExamRoom.getRemark());
            map.put("考场校验状态（0：未校验，1：已校验）", kwExamRoom.getStatus());
            map.put("考场校验备注", kwExamRoom.getCheckRemark());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Page<KwExamRoom> findAllExamRoom(Integer pageNo, Integer pageSize) {
        return null;
    }
}